import os
import sys
import urllib
from datetime import datetime
import logging

from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.api import urlfetch

import AppEnv
import base.Error as Error
import AppConfig
import Blog
import Tag
import utils

__all__ = [
    'Post',
    'new_post',
    'edit_post',
    'checkAll',
    'getArlist',
    ]

class Post(db.Model):
    blog = db.ReferenceProperty(Blog.Blog, required=True)
    title = db.StringProperty(required=True)
    uid = db.StringProperty(required=True)
    date = db.DateTimeProperty(required=True)
    published = db.BooleanProperty(required=True)
    content = db.TextProperty(required=True)
    tags = db.StringListProperty()
    comments = db.ListProperty(db.Key)
    references = db.ListProperty(db.Link)
    trackbacks = db.ListProperty(db.Key)

    def comment_count(self):
        return len(self.comments)

    def getTags(self):
        return map(utils.toPageString, self.tags)

    def delete(self):
        #update tag count
        Tag.updateTags(self.blog, self.tags,[])
        self.blog.updatePost(-1)
        
        for comment in self.comments:
            db.get(comment).delete()
        for tb in self.trackbacks:
            db.get(tb).delete()

        db.Model.delete(self)

    def pingReferences(self):
        ping_fields = {
            'title': utils.toPageString(self.title),
            'blog_name': utils.toPageString(self.blog.blogName),
            'url': None,
            'excerpt': utils.toPageString(self.content[250:]),
            }
        for url in self.references:
            try:
                ping_fields['url'] = '%s%s/%s/post/%s' % (
                    utils.toPageString(AppConfig.getAppConfig().HostURL),
                    AppEnv.apppath,
                    self.blog.blogId,
                    self.uid
                    )
                form_data = urllib.urlencode(ping_fields)
                resp = urlfetch.fetch(url=url,
                             payload=form_data,
                             method=urlfetch.POST,
                             headers={'Content-Type': 'application/x-www-form-urlencoded'},
                             allow_truncated=False)
                theSucceedResponseShouldBeLike = '''<?xml version="1.0" encoding="utf-8"?><response><error>0</error></response>'''
            except Exception,e:
                logging.debug(e)

__UID_REPLACE__ = [(' ','_'),
                   (',','_'),
           ]
def genPostUID(title):
    for token in __UID_REPLACE__:
        title = title.replace(token[0],token[1])
    title = urllib.quote_plus(title)
    uid = title
    pl = Post.all().filter("uid = ",uid).fetch(limit=1)
    if len(pl)>0:
        template = '_%d'
        i = 0
        while len(pl)>0:
            i += 1
            uid = title + (template % i)
            pl = Post.all().filter("uid = ",uid).fetch(limit=1)

    return uid

def new_post(blog, title, content, tags, references=None, author=None, publish=True):
    #uid
    uid = genPostUID(utils.toPageString(title))

    if not references:
        references = []
    if not author:
        author = blog.owner

    tags = map(utils.toDBString,tags)
    
    post = Post(blog = blog,
                title = utils.toDBString(title),
                uid = uid,
                date = datetime.now(),
                published = publish,
                content = utils.toDBText(content),
                comments = [],
                tags = tags,
                references = references,
                )

    if publish:
        #update tag count
        Tag.updateTags(blog, [], tags)
    
        blog.updatePost(1)
        
        #ping references
        post.pingReferences()
    
    post.put()
    return uid

def edit_post(blog, uid, title, content,tags,references=None,author=None,publish=True):
    posts = Post.all().filter('blog = ', blog).filter('uid = ',uid).fetch(limit=1)
    if not posts:
        raise Error.PageNotFoundError()
    else:
        post = posts[0]

    if not references:
        references = []
        
    tags = map(utils.toDBString,tags)

    if post.published:
        oldtags = post.tags
    else:
        oldtags = []
    if publish:
        newtags = tags
    else:
        newtags = []


    if not author:
        author = blog.owner

    post.title = utils.toDBString(title)
    post.author = author
    post.content = utils.toDBText(content)
    post.published = publish
    post.tags = tags
    post.references = references
    
    if publish:
        #update tag count
        Tag.updateTags(blog, oldtags,newtags)
        #ping references
        post.pingReferences()

    post.put()

def publish_post(blog, uid, publish=True):
    posts = Post.all().filter('blog = ', blog).filter('uid = ',uid).fetch(limit=1)
    if not posts:
        raise Error.PageNotFoundError()
    else:
        post = posts[0]

    if post.published:
        oldtags = post.tags
    else:
        oldtags = []

    if publish:
        newtags = post.tags
    else:
        newtags = []
        
    post.published = publish

    #update tag count
    Tag.updateTags(blog, oldtags, newtags)

    if publish:
        #ping references
        post.pingReferences()

    post.put()

    return post
    
def delete_post(uid):
    posts = Post.all().filter('uid = ',uid).fetch(limit=1)
    if not posts:
        raise Error.PageNotFoundError()
    else:
        post = posts[0]

    post.delete()

def checkTitle(title):
    if len(title) == 0:
        return False,'title is empty'
    if len(title) > 100:
        return False,'title is too long(must below 100)'
    return True,''

def checkContent(title):
    if len(title) == 0:
        return False,'Content is empty'
    return True,''

def checkAll(title,content):
    cl = [
        checkTitle(title),
        checkContent(content),
          ]
    return all([cr[0] for cr in cl]),[cr[1] for cr in cl]

def getArlist(blog=None):
    fetcher = Post.all().filter('published = ',True)

    if blog:
        fetcher = fetcher.filter('blog = ',blog)
    firstPost = fetcher.order('date').fetch(limit=1)
    #all archives
    if firstPost:
        firstPost = firstPost[0]
        firstDate = firstPost.date
        arlist = []       #archive list
        now = datetime.now()
        year = now.year
        month = now.month
        while firstDate.year*100+firstDate.month<=year*100+month:
            # start date of the month
            stdt = datetime(year=year,month=month,day=1)
            # start date of the next month
            eddt = utils.addMonth(stdt)

            fetcher = Post.all().filter('published = ',True)
            if blog:
                fetcher = fetcher.filter('blog = ',blog)
            arlist.append({'ar': stdt,
                           'count': fetcher.filter('date >= ', stdt).filter('date < ', eddt).count()})
            if month == 1:
                year -= 1
                month = 12
            else:
                month -= 1
    else:
        arlist = None
        
    return arlist

